# Title     : TODO
# Objective : TODO
# Created by: Administrator
# Created on: 2019/8/19

library(KEGGREST)
library(dplyr)
library(plyr)

extract_the_compound <- function(input_lines){
    ## 判断是否含有cpd:
    final <- c()
    for ( kkk in 1:length(input_lines)){
        each_input_lines <-  input_lines[kkk]
        IS_cpd_in <-  grepl ("cpd:",each_input_lines)
        if(IS_cpd_in){ ## 若有cpd: ， 则提取cpd:后面的字段
            final[kkk]    <-  each_input_lines %>% sub ( ".*cpd:([a-zA-Z]+[0-9]+)\".*" ,"\\1", . )
        }else { ## 若无cpd，则提取出名字，且仅提取第一个（有的会有两个ID，同物质双名）
            final[kkk] <-  each_input_lines %>% sub(".*name=\\\"[a-zA-Z]+:([a-zA-Z0-9]+).*\\\"/>","\\1",.)
        }
    }
    return(final)
}

jia_kegg_reaction_catcher <- function (  pathway_name = "rno00030") {  #### 输入一个代谢通路名，如"rno00030" ， 下载并获取该代谢通路的所有内容，并将代谢通路内部的 反应关系提取整理出来做为返回值。

    ### 获取通路信息 和 url ， 通过 KEGG API 对 网络数据库进行访问，下载 kgml 文件。
    pathway_note <-  pathway_name
    url <-  paste0 (  "http://rest.kegg.jp/get/",  pathway_note      , "/kgml" )
    # url

    ## 对通路进行解析 ， 提取其中的 反应关系。
    kgml  <-    readLines ( url )

    title_linenum <-  (kgml %>% grepl ("title=",.) ) %>% which()
    pathway_full_name <-  kgml[title_linenum] %>% sub(".*title=\\\"(.*)\\\"","\\1",.)
    ### 2.1 提取开始节点和结束节点

    start_lines <-  ( grepl ( "<reaction id=\\\"", kgml ) == T ) %>% which()
    end_lines   <-  ( grepl ( "</reaction>$", kgml ) == T )      %>% which()

    reaction_nums <-    start_lines %>% length()
    if ( reaction_nums == 0 ) {
        cat ( "\nThe pathway " , pathway_name , " doesn't have any reaction between compounds!\n")

        return ()
    }
    if ( length(start_lines) != length(end_lines) ){cat ( "Something might goes wrong with your KGML file, cause the starts sign of reaction is different from the ends sign.\n KGML文件解析后，反应开头的标识比反应结束标识多，你快瞅瞅是咋回事儿啊!")}

    for ( i in 1:length(start_lines )) {
        if ( i == 1 ) { pooled_reaction_block <-  data.frame() }

        temp_reaction_information       <-  kgml [ start_lines[ i ]:end_lines[ i ] ]
        temp_reaction_block <- data.frame (    pathway_note = pathway_note,  temp_reaction_id = i , reaction_information = temp_reaction_information )

        pooled_reaction_block <-  rbind ( pooled_reaction_block , temp_reaction_block )
    }

    pooled_reaction_block %>% head ()
    pooled_reaction_block %>% nrow ()

    # temp_zz <-  "<reaction id=\"157\" name=\"rn:R02736 rn:R10907\" type= nihaoaiyouwei"     %>% gsub(".*name=\"([rn:R0-9 ]+).*", "\\1", . )
    #
    # temp_zz %>% gsub("rn:","", . ) %>% gsub ( " ","&", . )

    processed_reactions  <-  ddply ( pooled_reaction_block , .( temp_reaction_id ) , function ( each_block ) {
        temp_reaction_name <-  each_block [ 1, "reaction_information"] %>% gsub(".*name=\"([rn:R0-9 ]+).*", "\\1", . )
        reaction_name      <- temp_reaction_name %>% gsub("rn:","", . ) %>% gsub ( " ","&", . )  ### 主要是应对一行中有多个反应的情况。 这样可以将多个反应的结果一同进行处理，结果之间用“&”进行连接。
        IS_reversible <-  each_block [ 1, "reaction_information"] %>% grepl ("type=\\\"reversible\\\"", . )  ### 判断是否是可逆反应，若是可逆反应，那么就反过来再弄一次
        ## 提取底物和产物行内容
        substrate_lines <-  each_block [ , "reaction_information"] %>% grepl ("substrate", . ) %>% which ( ) %>%  each_block [  . , "reaction_information"]
        product_lines   <-  each_block [ , "reaction_information"] %>% grepl ("product"  , . ) %>% which ( ) %>%  each_block [  . , "reaction_information"]
        ## 提取底物和产物内部信息
        # substrate_id    <-  substrate_lines %>% sub ( ".*cpd:(C[0-9]+)\".*" ,"\\1", . )
        # product_id      <-    product_lines %>% sub ( ".*cpd:(C[0-9]+)\".*" ,"\\1", . )
        ## ID前缀拓展为不定长度不定字母。
        # substrate_id    <-  substrate_lines %>% sub ( ".*cpd:([a-zA-Z]+[0-9]+)\".*" ,"\\1", . )
        # product_id      <-    product_lines %>% sub ( ".*cpd:([a-zA-Z]+[0-9]+)\".*" ,"\\1", . )
        ## 不止有cpd： 这一种开头，利用正则表达式提取下面的两行
        # <product id="6262" name="gl:G10599"/>
        # <product id="3169" name="cpd:C01246"/>
        ## 更新后的ID。
        # substrate_id <-  substrate_lines %>% sub(".*name=\\\"[a-zA-Z]+:(.*)\\\"/>","\\1",.)
        # product_id   <-    product_lines %>% sub(".*name=\\\"[a-zA-Z]+:(.*)\\\"/>","\\1",.)
        ## 有的是连号的，服了， 要确保只取到1个。
        substrate_id <-    extract_the_compound(substrate_lines)
        product_id   <-    extract_the_compound(product_lines)

        ## 将底物和产物提取并且进行组合。
        substrate_temp  <-  rep( substrate_id , rep (length(product_id) ,length( substrate_id ) )   )
        product_temp    <-  rep( product_id ,   length(substrate_id))

        substrate_and_product <-  data.frame ( substrate = substrate_temp , product = product_temp , stringsAsFactors = F)
        if ( IS_reversible == T ) {  ## 如果是可逆反应，就将之前的底物和产物交换位置，叠加到原有的数据框中
            mirror_substrate_and_product <-  data.frame ( substrate = product_temp , product = substrate_temp , stringsAsFactors = F)
            substrate_and_product <-  rbind ( substrate_and_product , mirror_substrate_and_product )
        }
        substrate_and_product
        output_block <-  data.frame (pathway_note = pathway_note, reaction_name  = reaction_name  , IS_reversible = IS_reversible,  substrate_and_product
        ,pathway_full_name = pathway_full_name, ### 增加了通路的全名
        stringsAsFactors = F)
        return ( output_block)
    })
    processed_reactions  ### 获取某个通路内所有的反应关系结果。
    return ( processed_reactions )
}

jia_kegg_reaction_pool_by_ori <-  function ( organism = "rno", file_path = ref_doc_path , file_name , force_renew = F, show_notes = T ){
    ## 使用 rno 代表大鼠， 使用 hsa 代表人。
    ## file_path 设定文件路径， 默认保存到  ref_doc_path 参考资料文件夹
    ## file_name 设定文件名称。
    ## Part 1 按照物种批量下载
    ## force_renew 设定是否强制更新数据库的信息

    file_name <-  paste0 ( file_path , file_name )
    if ( file.exists(  file_name ) & force_renew == F ) {
        ### 如果已经生成了相应的代谢通路的反应信息，就不用再跑一遍了
        if (show_notes == T ) {
            cat("The file: \n\t", file_name, " \nhas already exists. So this procedure has been skipped. If you still want to renew the information, please change the 'force_renew' as 'T' to renew the pathway reaction information in force.\n因为已经整理过一遍这个代谢通路信息了，所以这次就不弄了，如果您想要更新一下数据库，那么可以把‘force_renew’参数更改为‘T’使得数据库中的代谢通路反应信息强制更新")
        }


        final_pooled_pathway <-  read.csv ( file_name )
        return( final_pooled_pathway )

    }



    ## 若文件不存在,则对指定物种的代谢通路进行下载和解析.
    result   <-  keggList("pathway", organism )
    pathways <-  result %>% names ( ) %>% gsub ( "path:" , "", . )

    for ( i in 1:length(pathways )) {
        if ( i == 1 ) { final_pooled_pathway <-  data.frame( stringsAsFactors = F )}
        each_pathway <-  jia_kegg_reaction_catcher( pathway_name =  pathways [ i ] )
        final_pooled_pathway <-  rbind ( final_pooled_pathway , each_pathway )
    }


    write.csv ( final_pooled_pathway ,  file_name )
    return ( final_pooled_pathway ) ### 返回反应结果。

}


jia_kegg_reaction_pool_by_ori("rno","./","out.csv")
